# +----------------------------------------------------------------------
# | ChatWork智能聊天办公系统
# +----------------------------------------------------------------------
# | 软件声明: 本系统并非自由软件,未经授权任何形式的商业使用均属非法。
# | 版权保护: 任何企业和个人不允许对程序代码以任何形式任何目的复制/分发。
# | 授权要求: 如有商业使用需求,请务必先与版权所有者取得联系并获得正式授权。
# +----------------------------------------------------------------------
# | Author: ChatWork Team <2474369941@qq.com>
# +---------------------------------------------------------------------
import time
from tortoise.expressions import Q
from tortoise.transactions import in_transaction
from hypertext import PagingResult
from common.utils.urls import UrlUtil
from common.enums.apply import DocsEnum
from common.enums.notice import NoticeEnum
from common.models.users import UserModel
from common.models.docs import DocsFilesModel
from common.models.docs import DocsRecordsModel
from common.postgres.public import PgDocumentsModel
from plugins.msg.driver import MsgDriver
from apps.admin.schemas.apply.docs import files_schema as schema


class DocsFilesService:

    @classmethod
    async def lists(cls, params: schema.DocsFilesSearchIn) -> PagingResult[schema.DocsFilesListVo]:
        """
        文档列表。

        Args:
            params (schema.DocsFilesSearchIn): 查询参数。

        Returns:
            PagingResult[schema.DocsFilesListVo]: 分页文档列表Vo。

        Author:
            zero
        """
        # 查询条件
        where = DocsFilesModel.build_search({
            "%like%": ["name"],
            "=": ["code"]
        }, params.__dict__)

        where.append(Q(is_delete=0))
        if params.user:
            condition = [Q(sn=params.user), Q(is_delete=0)]
            users = await UserModel.filter(*condition).limit(200).values("id")
            ids = [int(item["id"]) for item in users] or [0]
            where.append(Q(user_id__in=ids))

        # 查询数据
        _model = DocsFilesModel.filter(*where).order_by("-id")
        _pager = await DocsFilesModel.paginate(
            model=_model,
            page_no=params.page_no,
            page_size=params.page_size,
            fields=DocsFilesModel.without_field("is_delete,delete_time")
        )

        # 查询用户
        userIds = [item["user_id"] for item in _pager.lists]
        users = await UserModel.queryUserDictsById(userIds)

        _lists = []
        for item in _pager.lists:
            user = users.get(item["user_id"]) or {}
            _lists.append(schema.DocsFilesListVo(
                id=item["id"],
                code=item["code"],
                name=item["name"],
                size=item["size"],
                ext=item["ext"],
                error=item["error"],
                status=item["status"],
                raw_path=await UrlUtil.to_absolute_url(item["raw_path"]),
                pdf_path=await UrlUtil.to_absolute_url(item["pdf_path"]),
                total_chat_count=item["total_chat_count"],
                total_use_points=item["total_use_points"],
                total_use_tokens=item["total_use_tokens"],
                ip=item["ip"],
                vector_alias=item["vector_alias"],
                create_time=item["create_time"],
                user={
                    "sn": user.get("sn", "").strip(),
                    "nickname": user.get("nickname", ""),
                    "mobile": user.get("mobile", ""),
                    "avatar": await UrlUtil.to_absolute_url(user.get("avatar", ""))
                }
            ))

        _pager.lists = _lists
        return _pager

    @classmethod
    async def dataset(cls, params: schema.DocsFilesDatesetIn) -> PagingResult[schema.DocsDatasetVo]:
        """
        文档数据。

        Args:
            params (schema.DocsFilesDatesetIn): 查询参数。

        Returns:
            PagingResult[schema.DocsDatasetVo]: 分页数据列表Vo。

        Author:
            zero
        """
        where = [Q(file_id=params.file_id)]
        _model = PgDocumentsModel.filter(*where).order_by("create_time", "chunk_index")
        _pager = await PgDocumentsModel.paginate(
            model=_model,
            page_no=params.page_no,
            page_size=params.page_size,
            fields=PgDocumentsModel.without_field("is_delete,delete_time")
        )

        _lists = []
        for item in _pager.lists:
            _lists.append(schema.DocsDatasetVo(
                uuid=str(item["uuid"]),
                page_nv=item["page_nv"],
                page_no=item["page_no"],
                chunk_index=item["chunk_index"],
                chunk_texts=item["chunk_texts"],
                dimension=item["dimension"],
                error=item["error"],
                status=item["status"],
                create_time=item["create_time"],
            ))
        _pager.lists = _lists
        return _pager

    @classmethod
    async def delete(cls, id_: int, reason: str):
        """
        文档删除。

        Args:
            id_ (int): 文档ID。
            reason (str): 删除原因。

        Author:
            zero
        """
        file = await DocsFilesModel.filter(id=id_, is_delete=0).get()
        async with in_transaction("mysql"):
            # 删除文件记录
            await DocsFilesModel.filter(id=id_).update(
                is_delete=1,
                delete_time=int(time.time())
            )

            # 删除对话记录
            await DocsRecordsModel.filter(file_id=id_).update(
                is_delete=1,
                delete_time=int(time.time())
            )

            # 发送用户通知
            await MsgDriver.send(scene=NoticeEnum.DOCS_DELETE, params={
                "user_id": file.user_id,
                "code": file.code,
                "name": file.name,
                "reason": reason
            })

    @classmethod
    async def retry(cls, id_: int):
        """
        重试训练

        Args:
            id_ (int): 文档ID。

        Author:
            zero
        """
        file = await DocsFilesModel.filter(id=id_, is_delete=0).get()
        file.status = DocsEnum.FILE_WAIT
        file.update_time = int(time.time())
        await file.save()
